import { Injectable, CanActivate, ExecutionContext, UnauthorizedException } from '@nestjs/common';
import { Reflector } from '@nestjs/core';
import { JwtService } from '@nestjs/jwt';

import { jwtConstants } from './constants';

@Injectable()
export class AuthGuard implements CanActivate {
    constructor(
        private readonly jwtService: JwtService,
        private reflector: Reflector,
    ) {}

    async canActivate(context: ExecutionContext): Promise<boolean> {
        // console.log('AuthGuard -> canActivate -> context', context);
        const isPublic = this.reflector.get<boolean>('isPublic', context.getHandler());
        if (isPublic) {
            // 如果路由被 @Public() 装饰，允许访问
            return true;
        }
        // 否则，执行你的鉴权逻辑
        // 获取header中的token信息
        const request = context.switchToHttp().getRequest();
        const token = extractToken(context);
        console.log('AuthGuard -> canActivate -> token', token);
        // 如果没有token，抛出异常
        if (!token) {
            throw new UnauthorizedException('请先登录');
        }

        // 否则验证token
        try {
            const payload = await this.jwtService.verifyAsync(token, {
                secret: jwtConstants.secret,
            });
            request.user = payload;
            console.log('AuthGuard -> canActivate -> payload', payload);
        } catch (error) {
            throw new UnauthorizedException('token验证失败');
        }
        return true;
    }
}

function extractToken(context: ExecutionContext) {
    const request = context.switchToHttp().getRequest();
    const { authorization } = request.headers;
    const [type, token] = authorization?.split(' ') ?? [];
    return type === 'Bearer' ? token : '';
}
